package com.gitee.wsl.compose.logger

import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import com.gitee.wsl.compose.base.useRef
import com.gitee.wsl.logger.LogLevel
import com.gitee.wsl.logger.Logger
import com.gitee.wsl.logger.debug

internal expect fun findComposableName() : String?

/**
 *
 * @Composable
 * fun VehicleUi(
 *     car: Car,
 *     bike: Bike,
 *     rocket: Rocket = Rocket(name = "Falcon 9"), // by default, everytime VehicleUi is recomposed, a new instance of Rocket will be created
 * ) {
 *     println("Vehicle recomposed")
 *
 *     Logger.WatchState(
 *         trackMap = mapOf(
 *             "car" to car,
 *             "bike" to bike,
 *             "rocket" to rocket
 *         ),
 *     )
 *     Column {
 *         Text("Car is $car")
 *         Text("Bike is $bike")
 *     }
 * }
 */

@Composable
fun Logger.WatchState(trackMap: Map<String, Any?>,
                      tag:String = "",
                      composableName: String? = findComposableName()
) {
    //if(level != LogLevel.DEBUG) return

    LaunchedEffect(Unit) {
        debug(tag, "🐞 Rebugger activated on `$composableName`")
    }

    val count = useRef(0)
    val flag = useRef(false)
    SideEffect {
        count.current++
    }

    val changeLog = StringBuilder()
    for ((key, newArg) in trackMap) {
        var recompositionTrigger by remember { mutableStateOf(false) }
        val oldArg = remember(recompositionTrigger) { newArg }
        val reason = when {
            oldArg != newArg -> {
                "`$key` changed from `$oldArg` to `$newArg`, "
            }

            oldArg !== newArg -> {
                "`$key` instance changed, but content remains the same -> `$oldArg`"
            }

            else -> {
                null
            }
        }
        if (reason != null) {
            changeLog.append("\n\t $reason")
            flag.current = true
            recompositionTrigger = !recompositionTrigger
        }
    }

    if (changeLog.isNotEmpty()) {
        debug(tag, "🐞$composableName recomposed because $changeLog")
    } else {
        if (count.current >= 1 && !flag.current) {
            debug(
                tag,
                "🐞$composableName recomposed, but reason is unknown. Are you sure you added all params to `trackMap`? 🤔"
            )
        } else {
            flag.current = false
        }
    }
}
